查看原文
其他

Spring源码之Context的创建核心逻辑(上)

SpringForAll社区 SpringForAll社区 2021-05-26

我们前一章介绍了spring的整体架构以及模块划分,也已经将代码导入ide中,那么接下来就要开始让人心动的Spring源码之旅了。

1、默认的Spring启动器

  1. @SpringBootApplication

  2. @ComponentScan(basePackages = {"com"})

  3. public class SpringSourceApplication {

  4. public static void main(String[] args) {

  5. ApplicationContext ctx = SpringApplication.run(SpringSourceApplication.class, args);

  6. }

  7. }

该方法是Springboot的启动类

2、进入SpringApplication.java

  1. public static ConfigurableApplicationContext run(Object source, String... args) {

  2. return run(new Object[] { source }, args);

  3. }

  4. public static ConfigurableApplicationContext run(Object[] sources, String[] args) {

  5. return new SpringApplication(sources).run(args);

  6. }

这里创建了一个SpringApplication方法,执行run方法,返回一个ConfigurableApplicationContext,这只是一个接口而已,根据名称来看,这是一个可配置的应用程序上下文。

3、进入RUN方法

SpringApplication(sources)这个类的初始化就先不看,这里面调用了initialize()方法,主要完成了当前的运行环境,以及设置了ApplicationListener相关的东西,这里我们先不做分析,直接进入run方法。

  1. public ConfigurableApplicationContext run(String... args) {

  2. //记录程序运行时间

  3. StopWatch stopWatch = new StopWatch();

  4. stopWatch.start();

  5. ConfigurableApplicationContext context = null;

  6. FailureAnalyzers analyzers = null;

  7. /**

  8. * 设置headless模式

  9. * 在我们的例子中该属性会被设置为true,因为我们开发的是服务器程序,

  10. * 一般运行在没有显示器和键盘的环境。关于java中的headless模式

  11. */

  12. configureHeadlessProperty();

  13. SpringApplicationRunListeners listeners = getRunListeners(args);

  14. listeners.starting();

  15. try {

  16. ApplicationArguments applicationArguments = new DefaultApplicationArguments(

  17. args);

  18. ConfigurableEnvironment environment = prepareEnvironment(listeners,

  19. applicationArguments);

  20. configureIgnoreBeanInfo(environment);

  21. bindToSpringApplication(environment);

  22. Banner printedBanner = printBanner(environment);

  23. /**

  24. * 它创建出来的是ConfigurableApplicationContext类的实例对象

  25. *AnnotationConfigEmbeddedWebApplicationContext

  26. */

  27. context = createApplicationContext();

  28. analyzers = new FailureAnalyzers(context);

  29. /**

  30. * 该方法对context进行了预设置,设置了ResourceLoader和ClassLoader,

  31. * 并向bean工厂中添加了一个beanNameGenerator

  32. */

  33. prepareContext(context, environment, listeners, applicationArguments,

  34. printedBanner);

  35. /**

  36. * prepareContext()已经做好了refresh上下文的基础准备工作

  37. * spring对ApplicationContext进行了向下转型,

  38. * 转型后的类型为:AbstractApplicationContex,并调用了它的refresh()方法

  39. * 详见方法内部实现

  40. */

  41. refreshContext(context);

  42. afterRefresh(context, applicationArguments);

  43. listeners.finished(context, null);

  44. stopWatch.stop();

  45. if (this.logStartupInfo) {

  46. new StartupInfoLogger(this.mainApplicationClass)

  47. .logStarted(getApplicationLog(), stopWatch);

  48. }

  49. return context;

  50. }

  51. catch (Throwable ex) {

  52. handleRunFailure(context, listeners, analyzers, ex);

  53. throw new IllegalStateException(ex);

  54. }

  55. }

try代码块中是我们最核心的功能,代码中也添加了一部分的注释。我们先看context的创建过程即进入到createApplicationContext()方法。

  1. protected ConfigurableApplicationContext createApplicationContext() {

  2. Class<?> contextClass = this.applicationContextClass;

  3. if (contextClass == null) {

  4. try {

  5. switch (this.webApplicationType) {

  6. case SERVLET:

  7. //此处采用反射获取WebApplicationContext

  8. contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);

  9. break;

  10. case REACTIVE:

  11. contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);

  12. break;

  13. default:

  14. contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);

  15. }

  16. }

  17. catch (ClassNotFoundException ex) {

  18. throw new IllegalStateException(

  19. "Unable create a default ApplicationContext, "

  20. + "please specify an ApplicationContextClass",

  21. ex);

  22. }

  23. }

  24. return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);

  25. }

DEFAULT_WEB_CONTEXT_CLASS—>AnnotationConfigEmbeddedWebApplicationContext接下来执行AnnotationConfigEmbeddedWebApplicationContext的构造方法

  1. public AnnotationConfigEmbeddedWebApplicationContext() {

  2. this.reader = new AnnotatedBeanDefinitionReader(this);

  3. this.scanner = new ClassPathBeanDefinitionScanner(this);

  4. }

上面实例化了 AnnotatedBeanDefinitionReader以及 ClassPathBeanDefinitionScanner实例化 AnnotatedBeanDefinitionReader

  1. public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {

  2. this(registry, getOrCreateEnvironment(registry));

  3. }

接下来是调用

  1. public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {

  2. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

  3. Assert.notNull(environment, "Environment must not be null");

  4. this.registry = registry;

  5. this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

  6. AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

  7. }

实例化 ConditionEvaluator,将其属性 ConditionContextImpl赋值

  1. AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);

具体实现如下:

  1. public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(

  2. BeanDefinitionRegistry registry, @Nullable Object source) {

  3. //获取beanfactory信息,Spring IOC的核心

  4. DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry)

  5. if (beanFactory != null) {

  6. if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {

  7. beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

  8. }

  9. if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {

  10. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());

  11. }

  12. }


  13. Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(4);


  14. if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  15. RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);

  16. def.setSource(source);

  17. beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

  18. }


  19. if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  20. RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);

  21. def.setSource(source);

  22. beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

  23. }


  24. if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  25. RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);

  26. def.setSource(source);

  27. beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

  28. }


  29. // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.

  30. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  31. RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);

  32. def.setSource(source);

  33. beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));

  34. }


  35. // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.

  36. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {

  37. RootBeanDefinition def = new RootBeanDefinition();

  38. try {

  39. def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,

  40. AnnotationConfigUtils.class.getClassLoader()));

  41. }

  42. catch (ClassNotFoundException ex) {

  43. throw new IllegalStateException(

  44. "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);

  45. }

  46. def.setSource(source);

  47. beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));

  48. }


  49. if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {

  50. RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);

  51. def.setSource(source);

  52. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));

  53. }

  54. if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {

  55. RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);

  56. def.setSource(source);

  57. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));

  58. }


  59. return beanDefs;

  60. }

上面代码比较长,我们来分开解析

  1. DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);


  2. 由wrap就可以看出此处使用的是装饰器模式,registry包裹成一个指定的beanFactory


  3. private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {

  4. if (registry instanceof DefaultListableBeanFactory) {

  5. return (DefaultListableBeanFactory) registry;

  6. }

  7. else if (registry instanceof GenericApplicationContext) {

  8. //此处 GenericApplicationContext构造函数初始化beanFactory为DefaultListableBeanFactory

  9. return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();

  10. }

  11. else {

  12. return null;

  13. }

  14. }


  15. 代码执行到`registry instanceof GenericApplicationContext`(通过类继承结构可得到),随后调用`GenericApplicationContext#getDefaultListableBeanFactory()方法,GenericApplicationContext`在构造方法中实例化了属性`beanFactory`的值为`DefaultListableBeanFactory`:


  16. public GenericApplicationContext() {

  17. this.beanFactory = new DefaultListableBeanFactory();

  18. }


  19. 其构造优先于`AnnotationConfigEmbeddedWebApplicationContext`构造方法执行。


  20. 以上获得了BeanFactory信息

代码的构建请参考 github该地址有相应代码的注释

Spring源码分析


推荐:一起了解下Java多线程基础

上一篇:程序员高效工具

点击原文阅读更多


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存